
/*
	Copyright (C) 2009 Salil Bhagurkar
	
	This file is part of ViSE
	
	ViSE is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	ViSE is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.
	
	You should have received a copy of the GNU Lesser General Public License
	along with ViSE.  If not, see <http://www.gnu.org/licenses/>.
*/

/*This file implements the application class that attaches to a node_fs structure.
*/


#include <shared.h>



//Wrapper for creating task in the system
int create_vtask(char *name, int (*init)(struct node_fs *), struct node *begin)
{
	struct node_fs *n;
	n = fs_create(name);
	n->init = init;
	n->class = malloc(sizeof(struct task));
	fs_link("/sched/tasks", n);
	sched_set_task_data(n, begin);
	return 0;
}

int switch_vtask(struct node_fs *to)
{
	return fs_write("/sched/tasks", to, 0, 0);
}


int vtask_generic(struct node_fs *this)
{
	struct node *begin;
	begin = sched_get_task_data(this);
	service(begin, NULL, REFER_SERVER);
	return 0;
}



#define NR_TEMP_LINKS 30

static void create_temp(struct app *app)
{
	app->temp_node = create_node(TYPE_VDATA, DATA_TYPE_VOID, 0, "temp", NR_TEMP_LINKS); //Temp node for attaching unlinked nodes
}


/*This function is called to create an application with name 'name'.*/
int app_create(char *location, char *name)
{
	struct node_fs *n;
	struct app *app;
	app = (struct app *)malloc(sizeof(struct app));
	n = fs_create(name); //Create a node for the application that has the name of the application
	n->class = app;
	app->fs = n;
	app->start_node = NULL; // This will be set by the application.
	n->type = TYPE_FS;
	create_temp(app);
	fs_link(location, n);
	set_editing_noparse(n);
	return 0;
}


int app_attach_temp(struct node *node)
{
	u32 i;
	struct node_fs *n;
	struct app *app;
	n = get_editing();
	app = (struct app *)n->class;
	for(i=0; i<NR_TEMP_LINKS; i++) {
		if(!(app->temp_node->client[i])) {
			app->temp_node->client[i] = node;
			return 0;
		}
	}
}

/*Here we add functions that will allow us to search throught the application for a given node that is being referred to.*/

struct node *app_find_node(char *name)
{
	struct node_fs *n;
	struct app *app;
	u32 i;
	n = get_editing();
	app = (struct app *)n->class;
	for(i=0; i<NR_TEMP_LINKS; i++) {
		if(app->temp_node->client[i]) {
			if(!strcmp(name, app->temp_node->client[i]->name)) {
				return app->temp_node->client[i];
			}
		} else
			return NULL;
	}
	return NULL;
}

void app_set_start_node(struct node *start_node)
{
	struct node_fs *n;
	struct app *app;
	n = get_editing();
	app = (struct app *)n->class;
	app->start_node = start_node;
}

void app_run(char *location)
{
	struct node_fs *n;
	struct app *app;
	struct node *begin_node;
	n = fs_get(location);
	app = (struct app *)n->class;
	begin_node = app->start_node;
	printk("app_run: %s\n", location);
	create_vtask(n->name, vtask_generic, begin_node);
}

void debug_temp()
{
	u32 i, j;
	struct node_fs *n;
	struct app *app;
	n = get_editing();
	app = (struct app *)n->class;
	printk("Debug temp at app %s\n", n->name);
	for(i=0; i<NR_TEMP_LINKS; i++) {
		if(app->temp_node->client[i]) {
			printk("temp#%u: %s\n", i, app->temp_node->client[i]->name);
			if(app->temp_node->client[i]->server) {
				printk("--server = %s\n", app->temp_node->client[i]->server->name);
			}
			if(app->temp_node->client[i]->nr_clients > 0) {
				for(j = 0; j < app->temp_node->client[i]->nr_clients; j++) {
					printk("--client%d = %s\n", j, app->temp_node->client[i]->client[j]->name);
				}
			}
		} else
			return;
	}
}
